/* 
 * File:   Reader.cpp
 * Author: Guilherme Monteiro
 * 
 */

#include "../headers/Reader.h"

Reader::Reader(string inputFilePath) throw (InvalidFileException) {
    try {
        setInputFilePath(inputFilePath);
    }
    catch(InvalidFileException &ife) {
        throw ife;
    }
}

Reader::Reader(const Reader& orig) {
}

Reader::~Reader() {
}

void Reader::setInputFilePath(string path) throw (InvalidFileException) {
    if(!path.empty()) {
        this->inputFilePath = path;
    }
    else {
        throw InvalidFileException(path);
    }
}

vector< vector<Cell> > Reader::readTables() {
    vector< vector<Cell> > tablesCells;
    
    File *f = new File(this->inputFilePath);
    vector<string> lines = f->readLines();
    
    vector<string>::iterator itLines;
    for(itLines = lines.begin(); itLines != lines.end(); itLines++) {
        if((*itLines)[0] == '#') {
            vector<Cell> cells;
            tablesCells.push_back(cells);
            continue; // ignore header of file
        }
        
        vector<CvPoint> points = transformDataInPoints(getData(*itLines));
        tablesCells[tablesCells.size()-1].push_back(Cell(points[0], points[1]));
    }
    
    return tablesCells;
}

/**
 * Returns a vector of cells
 * read of the input file.
 * 
 * @return vector of cells.
 */
vector<Cell> Reader::readCells() {
    vector<Cell> cells;
    vector<CvPoint>::iterator itPoints;
    
    vector<CvPoint> points = readPoints();
    
    for(itPoints = points.begin(); itPoints != points.end(); itPoints++) {
        CvPoint current = *itPoints; // LU
        CvPoint next = *(++itPoints); // RB
        cells.push_back(Cell( current, next));
    }
    
    return cells;
}

/**
 * Return points read of input file.
 * 
 * NOTE: Lines started with # (header of file)
 * are ignored and don't are included in returned 
 * vector.
 * 
 * @return vector of points
 */
vector<CvPoint> Reader::readPoints() {
    vector<CvPoint> points;
    
    File f(this->inputFilePath);
    vector<string> lines = f.readLines();
    
    vector<string>::iterator it_lines;
    for(it_lines=lines.begin(); it_lines!=lines.end(); it_lines++) {
        if((*it_lines).empty())
            break;
        
        if((*it_lines)[0] == '#') // ignore header
            continue;
        
//        printf("\nline: %s\n", (*it_lines).c_str());
        
        vector<string> data = getData(*it_lines);
        vector<CvPoint> transformedData = transformDataInPoints(data);
        
//        printf("\nleft upper: (%d, %d)\n", leftUpper.x, leftUpper.y);
//        printf("right bottom: (%d, %d)\n\n", rightBottom.x, rightBottom.y);
        
        points.push_back(transformedData[0]);
        points.push_back(transformedData[1]);
    }
    
    //printf("points size in transformPointsToCvPoints(): %d\n", points.size());
    return points;
}

/**
 * Return vector of points extracted from data.
 * 
 * @param data: vector of string in format {'x1','y1','x2','y2'}
 * @return vector of points: points[0]: leftUpper, points[1]: rightBottom
 */
vector<CvPoint> Reader::transformDataInPoints(vector<string> data) {
    CvPoint leftUpper, rightBottom;
    vector<string>::iterator itData;
    
    for(itData=data.begin(); itData!=data.end();) {
        leftUpper.x = atoi((*(itData++)).c_str());
        leftUpper.y = atoi((*(itData++)).c_str());
        rightBottom.x = atoi((*(itData++)).c_str());
        rightBottom.y = atoi((*(itData++)).c_str());
    }
    
    vector<CvPoint> points;
    points.push_back(leftUpper);
    points.push_back(rightBottom);
    
    return points;
}

/**
 * Returns a vector of string with
 * each data split for comma in
 * a line of the file.
 * 
 * @param line
 * @return vector of data
 */
vector<string> Reader::getData(string line) {
    vector<string> nums;
    int i = 0; // position in line
    char a = line.at(i);
    
    string num = "";
    for(int j = 0; j < 4; j++) { // are 3 commas
        while(a != ',' && i < line.length()) {
            num += a;
            if(i+1 == line.length())
                break;
            a = line.at(++i);
        }
        if(a == ',') {
            a = line.at(++i);
        }
        nums.push_back(num);
        num = "";
    }
    return nums;
}